home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xpaint-2.1.1 / selectOp.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  21KB  |  754 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com)            | */
  3. /* |                                                                   | */
  4. /* | Permission to use, copy, modify, and to distribute this software  | */
  5. /* | and its documentation for any purpose is hereby granted without   | */
  6. /* | fee, provided that the above copyright notice appear in all       | */
  7. /* | copies and that both that copyright notice and this permission    | */
  8. /* | notice appear in supporting documentation.  There is no           | */
  9. /* | representations about the suitability of this software for        | */
  10. /* | any purpose.  this software is provided "as is" without express   | */
  11. /* | or implied warranty.                                              | */
  12. /* |                                                                   | */
  13. /* +-------------------------------------------------------------------+ */
  14.  
  15. #include <X11/Intrinsic.h>
  16. #include <X11/StringDefs.h>
  17. #include <X11/cursorfont.h>
  18. #include <X11/Xaw/Toggle.h>
  19. #include <X11/Xaw/Form.h>
  20. #include <X11/Xaw/Scrollbar.h>
  21. #include <X11/Xaw/AsciiText.h>
  22. #include <X11/Xaw/Command.h>
  23. #include <X11/Shell.h>
  24. #include <stdio.h>
  25. #include "xpaint.h"
  26. #include "misc.h"
  27. #include "Paint.h"
  28. #include "palette.h"
  29.  
  30. /*
  31. **  It is now historical, that the Box and Area selection
  32. **    operations are contained in the same file.
  33. */
  34.  
  35. static int        cutMode = 0;
  36. static unsigned char    backgroundRGB[3] = { 255, 255, 255 };
  37. static unsigned char    varianceRGB[3] = { 0, 0, 0 };
  38.  
  39. typedef struct {
  40.     Boolean        area;        /* area or box */
  41.     Boolean        lastType;
  42.  
  43.     Widget        w;
  44.     Drawable    drawable;
  45.  
  46.     Boolean        drawn;
  47.  
  48.     int        wx, wy, dx, dy;
  49.  
  50.     /*
  51.     **  The point region for area operators
  52.     */
  53.     int        size, npoint;
  54.     XPoint        *real_p, *window_p;
  55.  
  56.     /*
  57.     **  The rectangles for a box
  58.     */
  59.     int        lastX, lastY;
  60.     XRectangle    rect;
  61.  
  62.     GC        gcx;
  63.  
  64.     /*
  65.     **  The interesting stuff, for the active region
  66.     **    the important part of pixBox is the width, height
  67.     **    the x,y is where it is presently located on the screen.
  68.     */
  69.     XRectangle    pixBox;
  70. } LocalInfo;
  71.  
  72. #define MKRECT(rect, sx, sy, ex, ey, typeFlag) do {            \
  73.     if (typeFlag) {                            \
  74.         (rect)->width  = MIN(ABS(sx - ex),ABS(sy - ey));    \
  75.         (rect)->height = (rect)->width;                \
  76.         (rect)->x = (ex - sx < 0) ? sx - (rect)->width : sx;    \
  77.         (rect)->y = (ey - sy < 0) ? sy - (rect)->height : sy;    \
  78.     } else {                            \
  79.         (rect)->x      = MIN(sx, ex);                \
  80.         (rect)->y      = MIN(sy, ey);                \
  81.         (rect)->width  = MAX(sx, ex) - (rect)->x;        \
  82.         (rect)->height = MAX(sy, ey) - (rect)->y;        \
  83.     }                                \
  84. } while (0)
  85.  
  86. /*
  87. **  press
  88. */
  89. static void    press(Widget w, LocalInfo *l, XButtonEvent *event, OpInfo *info) 
  90. {
  91.     /*
  92.     **  Check to make sure all buttons are up, before doing this
  93.     */
  94.     if ((event->state & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)) != 0)
  95.         return;
  96.  
  97.     if (info->surface == opWindow) {
  98.         l->w     = w;
  99.     
  100.         l->wx = event->x;
  101.         l->wy = event->y;
  102.  
  103.         l->drawn = False;
  104.  
  105.         return;
  106.     }
  107.     
  108.     /*
  109.     **  Must be on the surface == pixmap now
  110.     */
  111.  
  112.     l->drawable = info->drawable;
  113.  
  114.     l->real_p[0].x = info->x;
  115.     l->real_p[0].y = info->y;
  116.     l->window_p[0].x = l->wx - info->zoom / 2;
  117.     l->window_p[0].y = l->wy - info->zoom / 2;
  118.     l->npoint = 1;
  119. }
  120.  
  121. static void    keyPress(Widget w, LocalInfo *l, XKeyEvent *event, OpInfo *info) 
  122. {
  123.     KeySym    keysym;
  124.     int    len, i;
  125.     char    buf[21];
  126.  
  127.         if ((len = XLookupString(event, buf, sizeof(buf) - 1, &keysym, NULL)) == 0)
  128.         return;
  129.  
  130.     /*
  131.     **  Look for either backspace or delete and remove region
  132.     */
  133.     for (i = 0; i < len; i++) {
  134.         if (buf[i] == 0x08 || buf[i] == 0x7f) {
  135.             PwRegionClear(w);
  136.             return;
  137.         }
  138.     }
  139. }
  140.  
  141. /*
  142. **  motion
  143. */
  144. static void    motionBoxBand(Widget w, LocalInfo *l, XMotionEvent *event, OpInfo *info) 
  145. {
  146.     XRectangle    rect;
  147.  
  148.     if (l->drawn) {
  149.         MKRECT(&rect, l->window_p[0].x, l->window_p[0].y, 
  150.                   l->lastX, l->lastY, l->lastType);
  151.         XDrawRectangles(XtDisplay(w), XtWindow(w), l->gcx, &rect, 1);
  152.     }
  153.  
  154.     l->lastX = event->x - info->zoom / 2;
  155.     l->lastY = event->y - info->zoom / 2;
  156.     l->lastType = (event->state & ShiftMask);
  157.  
  158.     if (l->drawn = (l->window_p[0].x != l->lastX && l->window_p[0].y != l->lastY)) {
  159.         MKRECT(&rect, l->window_p[0].x, l->window_p[0].y, 
  160.                 l->lastX, l->lastY, l->lastType);
  161.         XDrawRectangles(XtDisplay(w), XtWindow(w), l->gcx, &rect, 1);
  162.     }
  163. }
  164. static void    motionAreaBand(Widget w, LocalInfo *l, XMotionEvent *event, OpInfo *info) 
  165. {
  166.     if (l->npoint != 0 && (l->real_p[l->npoint - 1].x == info->x) && (l->real_p[l->npoint - 1].y == info->y))
  167.         return;
  168.  
  169.     l->window_p[l->npoint].x = event->x;
  170.     l->window_p[l->npoint].y = event->y;
  171.     l->real_p[l->npoint].x = info->x;
  172.     l->real_p[l->npoint].y = info->y;
  173.  
  174.     XDrawLine(XtDisplay(w), XtWindow(w), l->gcx,
  175.         l->window_p[l->npoint-1].x,
  176.         l->window_p[l->npoint-1].y,
  177.         l->window_p[l->npoint].x,
  178.         l->window_p[l->npoint].y);
  179.     XDrawPoint(XtDisplay(w), XtWindow(w), l->gcx,
  180.         l->window_p[l->npoint].x,
  181.         l->window_p[l->npoint].y);
  182.         
  183.         
  184.     l->npoint++;
  185.  
  186.     if (l->npoint > l->size - 3) {
  187.         l->size += 256;
  188.         l->real_p = (XPoint*)XtRealloc((XtPointer)l->real_p,
  189.                     l->size * sizeof(XPoint));
  190.         l->window_p = (XPoint*)XtRealloc((XtPointer)l->window_p,
  191.                     l->size * sizeof(XPoint));
  192.     }
  193. }
  194. static void    motion(Widget w, LocalInfo *l, XMotionEvent *event, OpInfo *info) 
  195. {
  196.     if (l->area)
  197.         motionAreaBand(w, l, event, info);
  198.     else
  199.         motionBoxBand(w, l, event, info);
  200. }
  201.  
  202. static Boolean    chromaCut(Widget w, LocalInfo *l, Pixmap *mask)
  203. {
  204.     GC        gc;
  205.     XImage        *src, *mimg;
  206.     XRectangle    *rect = PwScaleRectangle(w, &l->pixBox);
  207.     int        x, y, count = 0;
  208.     Pixel        p;
  209.     XColor        *xcol;
  210.     int        br, bg, bb;
  211.     int        vr, vg, vb;
  212.     int        pr, pg, pb;
  213.     Boolean        mode = (cutMode == 1);
  214.     Palette        *map;
  215.     Colormap    cmap;
  216.     int        step;
  217.  
  218.     src = PwGetImage(w, rect);
  219.     XtVaGetValues(GetShell(w), XtNcolormap, &cmap, NULL);
  220.     map = PaletteFind(w, cmap);
  221.  
  222.     if (*mask != None) {
  223.         mimg = XGetImage(XtDisplay(w), *mask, 0, 0, rect->width, rect->height, AllPlanes, ZPixmap);
  224.     } else {
  225.         char    *data = (char*)XtMalloc(rect->width * rect->height * sizeof(long));
  226.         int        i;
  227.  
  228.         mimg = NewXImage(XtDisplay(w), DefaultVisualOfScreen(XtScreen(w)), 1, rect->width, rect->height);
  229.  
  230.         memset(mimg->data, ~0, rect->height * mimg->bytes_per_line);
  231.     }
  232.  
  233.     br = backgroundRGB[0];
  234.     bg = backgroundRGB[1];
  235.     bb = backgroundRGB[2];
  236.     vr = varianceRGB[0];
  237.     vg = varianceRGB[1];
  238.     vb = varianceRGB[2];
  239.  
  240.     if (rect->height * rect->width > 2048)
  241.         StateSetBusy(True);
  242.     step = 256 * 64 / rect->width;
  243.  
  244.     for (y = 0; y < rect->height; y++) {
  245.         for (x = 0; x < rect->width; x++) {
  246.             if (!XGetPixel(mimg, x, y))
  247.                 continue;
  248.  
  249.             p = XGetPixel(src, x + rect->x, y + rect->y);
  250.  
  251.             xcol = PaletteLookup(map, p);
  252.             pr = (xcol->red >> 8) & 0xff;
  253.             pg = (xcol->green >> 8) & 0xff;
  254.             pb = (xcol->blue >> 8) & 0xff;
  255.  
  256.             if (((br - vr) <= pr && pr <= (br + vr) &&
  257.                  (bg - vg) <= pg && pg <= (bg + vg) &&
  258.                  (bb - vb) <= pb && pb <= (bb + vb)) == mode)
  259.                 XPutPixel(mimg, x, y, False);
  260.             else
  261.                 count++;
  262.         }
  263.         if (y % step == 0)
  264.             StateTimeStep();
  265.     }
  266.  
  267.     if (count != 0) {
  268.         /*
  269.         **  Not a solid region.
  270.         */
  271.  
  272.         if (*mask == None)
  273.             *mask = XCreatePixmap(XtDisplay(w), XtWindow(w), rect->width, rect->height, 1);
  274.         gc = XCreateGC(XtDisplay(w), *mask, 0, 0);
  275.         XPutImage(XtDisplay(w), *mask, gc, mimg, 0, 0, 0, 0, rect->width, rect->height);
  276.         XFreeGC(XtDisplay(w), gc);
  277.     }
  278.  
  279.     XDestroyImage(mimg);
  280.  
  281.     if (rect->height * rect->width > 2048)
  282.         StateSetBusy(False);
  283.  
  284.  
  285.     return count != 0;
  286. }
  287.  
  288. static void    releaseBoxBand(Widget w, LocalInfo *l, XButtonEvent *event, OpInfo *info) 
  289. {
  290.     XRectangle    rect;
  291.     int        width, height;
  292.  
  293.     MKRECT(&rect, l->window_p[0].x, l->window_p[0].y, l->lastX, l->lastY, l->lastType);
  294.     if (l->drawn) 
  295.         XDrawRectangles(XtDisplay(w), XtWindow(w), l->gcx, &rect, 1);
  296.     
  297.  
  298.     MKRECT(&l->pixBox, l->real_p[0].x, l->real_p[0].y, info->x, info->y, l->lastType);
  299.     XtVaGetValues(w, XtNdrawWidth, &width, XtNdrawHeight, &height, NULL);
  300.  
  301.     if (l->pixBox.x + l->pixBox.width > width) 
  302.         l->pixBox.width = width - l->pixBox.x;
  303.     if (l->pixBox.y + l->pixBox.height > height) 
  304.         l->pixBox.height = height - l->pixBox.y;
  305.     if (l->pixBox.x < 0) {
  306.         l->pixBox.width += l->pixBox.x;
  307.         l->pixBox.x = 0;
  308.     }
  309.     if (l->pixBox.y < 0) {
  310.         l->pixBox.height += l->pixBox.y;
  311.         l->pixBox.y = 0;
  312.     }
  313. }
  314. static Boolean    releaseAreaBand(Widget w, LocalInfo *l, XButtonEvent *event, OpInfo *info, Pixmap *mask) 
  315. {
  316.     int    xmax, xmin, ymax, ymin;
  317.     int    width, height, i;
  318.     GC    gc;
  319.     XPoint    tmp;
  320.  
  321.     XDrawLines(XtDisplay(w), XtWindow(w), l->gcx,
  322.             l->window_p, l->npoint, CoordModeOrigin);
  323.     
  324.     if (l->npoint <= 2) 
  325.         return False;
  326.     
  327.     l->window_p[l->npoint] = l->window_p[0];
  328.     l->real_p[l->npoint]   = l->real_p[0];
  329.     l->npoint++;
  330.     
  331.     xmin = xmax = l->real_p[0].x;        
  332.     ymin = ymax = l->real_p[0].y;
  333.     for (i = l->npoint - 1; i > 0; i--) {
  334.         xmin = MIN(xmin, l->real_p[i].x);
  335.         ymin = MIN(ymin, l->real_p[i].y);
  336.         xmax = MAX(xmax, l->real_p[i].x);
  337.         ymax = MAX(ymax, l->real_p[i].y);
  338.  
  339.         l->window_p[i].x = l->window_p[i].x - l->window_p[i-1].x;
  340.         l->window_p[i].y = l->window_p[i].y - l->window_p[i-1].y;
  341.         l->real_p[i].x   = l->real_p[i].x   - l->real_p[i-1].x;
  342.         l->real_p[i].y   = l->real_p[i].y   - l->real_p[i-1].y;
  343.     }
  344.  
  345.     XYtoRECT(xmin, ymin, xmax, ymax, &l->pixBox);
  346.     XtVaGetValues(w, XtNdrawWidth, &width, XtNdrawHeight, &height, NULL);
  347.     if (l->pixBox.x + l->pixBox.width > width)
  348.         l->pixBox.width = width - l->pixBox.x;
  349.     if (l->pixBox.y + l->pixBox.height > height) 
  350.         l->pixBox.height = height - l->pixBox.y;
  351.     if (l->pixBox.x < 0) {
  352.         l->pixBox.width += l->pixBox.x;
  353.         l->pixBox.x = 0;
  354.     }
  355.     if (l->pixBox.y < 0) {
  356.         l->pixBox.height += l->pixBox.y;
  357.         l->pixBox.y = 0;
  358.     }
  359.  
  360.     *mask = XCreatePixmap(XtDisplay(w), XtWindow(w), 
  361.                 l->pixBox.width, l->pixBox.height, 1);
  362.     gc = XCreateGC(XtDisplay(w), *mask, 0, 0);
  363.     XSetFunction(XtDisplay(w), gc, GXclear);
  364.     XFillRectangle(XtDisplay(w), *mask, gc, 0, 0, l->pixBox.width, l->pixBox.height);
  365.     XSetFunction(XtDisplay(w), gc, GXset);
  366.     tmp = l->real_p[0];
  367.     l->real_p[0].x = l->dx = l->real_p[0].x - xmin;
  368.     l->real_p[0].y = l->dy = l->real_p[0].y - ymin;
  369.     XFillPolygon(XtDisplay(w), *mask, gc, l->real_p, l->npoint, 
  370.                 Complex, CoordModePrevious);
  371.     l->real_p[0] = tmp;
  372.  
  373.     XFreeGC(XtDisplay(w), gc);
  374.  
  375.     return True;
  376. }
  377. static void    release(Widget w, LocalInfo *l, XButtonEvent *event, OpInfo *info) 
  378. {
  379.     int    mask;
  380.     Pixmap    mpix;
  381.  
  382.     /*
  383.     **  Check to make sure all buttons are up, before doing this
  384.     */
  385.     mask = Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask;
  386.     switch (event->button) {
  387.     case Button1:    mask ^= Button1Mask; break;
  388.     case Button2:    mask ^= Button2Mask; break;
  389.     case Button3:    mask ^= Button3Mask; break;
  390.     case Button4:    mask ^= Button4Mask; break;
  391.     case Button5:    mask ^= Button5Mask; break;
  392.     }
  393.     if ((event->state & mask) != 0)
  394.         return;
  395.  
  396.     mpix = None;
  397.  
  398.     if (l->area) {
  399.         if (releaseAreaBand(w, l, event, info, &mpix) == False) {
  400.             PwRegionFinish(w, True);
  401.             return;
  402.         }
  403.     } else {
  404.         releaseBoxBand(w, l, event, info);
  405.     }
  406.  
  407.     if (l->pixBox.width <= 1 || l->pixBox.height <= 1) {
  408.         PwRegionFinish(w, True);
  409.         return;
  410.     }
  411.     if (cutMode != 0 && !chromaCut(w, l, &mpix)) {
  412.         PwRegionFinish(w, True);
  413.         return;
  414.     }
  415.  
  416.     PwRegionSet(w, &l->pixBox, None, mpix);
  417. }
  418.  
  419. /*
  420. **  Those public functions
  421. */
  422. void *SelectBoxAdd(Widget w)
  423. {
  424.     LocalInfo    *l = (LocalInfo*)XtMalloc(sizeof(LocalInfo));
  425.  
  426.     l->area     = False;
  427.     l->lastType = False;
  428.     l->gcx      = GetGCX(w);
  429.  
  430.     l->size     = 8;
  431.     l->real_p   = (XPoint *)XtCalloc(sizeof(XPoint), l->size);
  432.     l->window_p = (XPoint *)XtCalloc(sizeof(XPoint), l->size);
  433.  
  434.     XtVaSetValues(w, XtNcompress, True, NULL);
  435.  
  436.     OpAddEventHandler(w, opWindow|opPixmap, ButtonPressMask, FALSE, (OpEventProc)press, l);
  437.     OpAddEventHandler(w, opWindow, ButtonMotionMask, FALSE, (OpEventProc)motion, l);
  438.     OpAddEventHandler(w, opWindow, ButtonReleaseMask, FALSE, (OpEventProc)release, l);
  439.  
  440.     OpAddEventHandler(w, opWindow, KeyPressMask, FALSE, (OpEventProc)keyPress, l);
  441.     SetCrossHairCursor(w);
  442.  
  443.     return l;
  444. }
  445. void SelectBoxRemove(Widget w, LocalInfo *l)
  446. {
  447.     OpRemoveEventHandler(w, opWindow|opPixmap, ButtonPressMask, FALSE, (OpEventProc)press, l);
  448.     OpRemoveEventHandler(w, opWindow, ButtonMotionMask, FALSE, (OpEventProc)motion, l);
  449.     OpRemoveEventHandler(w, opWindow, ButtonReleaseMask, FALSE, (OpEventProc)release, l);
  450.     OpRemoveEventHandler(w, opWindow, KeyPressMask, FALSE, (OpEventProc)keyPress, l);
  451.     PwRegionFinish(w, False);
  452.  
  453.     XtFree((XtPointer)l->window_p);
  454.     XtFree((XtPointer)l->real_p);
  455.     XtFree((XtPointer)l);
  456. }
  457.  
  458. void *SelectAreaAdd(Widget w)
  459. {
  460.     LocalInfo    *l = (LocalInfo*)XtMalloc(sizeof(LocalInfo));
  461.  
  462.     l->area   = True;
  463.     l->gcx    = GetGCX(w);
  464.  
  465.     XtVaSetValues(w, XtNcompress, False, NULL);
  466.  
  467.     l->size     = 256;
  468.     l->real_p   = (XPoint *)XtCalloc(sizeof(XPoint), l->size);
  469.     l->window_p = (XPoint *)XtCalloc(sizeof(XPoint), l->size);
  470.  
  471.     OpAddEventHandler(w, opWindow|opPixmap, ButtonPressMask, FALSE, (OpEventProc)press, l);
  472.     OpAddEventHandler(w, opWindow, ButtonMotionMask, FALSE, (OpEventProc)motion, l);
  473.     OpAddEventHandler(w, opWindow, ButtonReleaseMask, FALSE, (OpEventProc)release, l);
  474.     OpAddEventHandler(w, opWindow, KeyPressMask, FALSE, (OpEventProc)keyPress, l);
  475.  
  476.     SetPencilCursor(w);
  477.  
  478.     return l;
  479. }
  480. void SelectAreaRemove(Widget w, LocalInfo *l)
  481. {
  482.     OpRemoveEventHandler(w, opWindow|opPixmap, ButtonPressMask, FALSE, (OpEventProc)press, l);
  483.     OpRemoveEventHandler(w, opWindow, ButtonMotionMask, FALSE, (OpEventProc)motion, l);
  484.     OpRemoveEventHandler(w, opWindow, ButtonReleaseMask, FALSE, (OpEventProc)release, l);
  485.     OpRemoveEventHandler(w, opWindow, KeyPressMask, FALSE, (OpEventProc)keyPress, l);
  486.     PwRegionFinish(w, False);
  487.  
  488.     XtFree((XtPointer)l->window_p);
  489.     XtFree((XtPointer)l->real_p);
  490.     XtFree((XtPointer)l);
  491. }
  492.  
  493. /*
  494. **  Dialog box
  495. */
  496. typedef struct {
  497.     Widget    redBar, greenBar, blueBar;
  498.     Widget    redText, greenText, blueText;
  499.     Widget    mode;
  500.     Widget    shell;
  501.     float    r, g, b;
  502.     float    vr, vg, vb;
  503.     Pixel    pixel;
  504. } DialogInfo;
  505.  
  506. static DialogInfo    *dInfo = NULL;
  507.  
  508. static void closePopup(Widget w, Widget shell)
  509. {
  510.     XtPopdown(shell);
  511. }
  512. static void barCB(Widget bar, DialogInfo *l, float *percent)
  513. {
  514.     Widget    t;
  515.     char    buf[20];
  516.  
  517.     if (l->redBar == bar) {
  518.         l->vr = *percent;
  519.         t = l->redText;
  520.     } else if (l->greenBar == bar) {
  521.         l->vg = *percent;
  522.         t = l->greenText;
  523.     } else if (l->blueBar == bar) {
  524.         l->vb = *percent;
  525.         t = l->blueText;
  526.     } else {
  527.         return;
  528.     }
  529.     sprintf(buf, "%d", (int)(255 * *percent));
  530.     XtVaSetValues(t, XtNstring, buf, NULL);
  531. }
  532.  
  533. static Widget addSB(Widget parent, Widget above, char *title, Widget *bar, Widget *text)
  534. {
  535.     Widget    form, label;
  536.  
  537.     form = XtVaCreateManagedWidget("form", formWidgetClass, parent,
  538.             XtNborderWidth, 0,
  539.             XtNfromVert, above,
  540.             NULL);
  541.     label = XtVaCreateManagedWidget("varianceLabel", labelWidgetClass, form,
  542.             XtNlabel, title,
  543.             XtNborderWidth, 0,
  544.             XtNright, XtChainLeft,
  545.             XtNleft, XtChainLeft,
  546.             NULL);
  547.     *bar = XtVaCreateManagedWidget("varianceBar", scrollbarWidgetClass, form,
  548.             XtNorientation, XtorientHorizontal,
  549.             XtNfromHoriz, label,
  550.             XtNleft, XtChainLeft,
  551.             NULL);
  552.     *text = XtVaCreateManagedWidget("varianceText", asciiTextWidgetClass, form,    
  553.                 XtNfromHoriz, *bar,
  554.             XtNeditType, XawtextEdit,
  555.             XtNwrap, XawtextWrapNever,
  556.                 XtNresize, XawtextResizeWidth,
  557.             XtNwidth, 50,
  558.             XtNlength, 5,
  559.             XtNstring, "0",
  560.             NULL);
  561.  
  562.     return form;
  563. }
  564. static void deltaCB(Widget w, DialogInfo *l, XtPointer junk)
  565. {
  566.     XColor        *xcol, xcol2;
  567.     int        dr, dg, db;
  568.     char        buf[20];
  569.  
  570.     xcol = DoGrabColor(w);
  571.     
  572.     xcol2.pixel = l->pixel;
  573.     XQueryColor(XtDisplay(w), DefaultColormapOfScreen(XtScreen(w)), &xcol2);
  574.  
  575.     dr = xcol->red - xcol2.red;
  576.     dg = xcol->green - xcol2.green;
  577.     db = xcol->blue - xcol2.blue;
  578.     if (dr < 0) dr = -dr;
  579.     if (dg < 0) dg = -dg;
  580.     if (db < 0) db = -db;
  581.  
  582.     l->vr = (float)((dr >> 8) & 0xff) / 255.0;
  583.     l->vg = (float)((dg >> 8) & 0xff) / 255.0;
  584.     l->vb = (float)((db >> 8) & 0xff) / 255.0;
  585.  
  586.     sprintf(buf, "%d", (int)(255 * l->vr));
  587.     XtVaSetValues(l->redText, XtNstring, buf, NULL);
  588.     XawScrollbarSetThumb(l->redBar, l->vr, -1.0);
  589.     sprintf(buf, "%d", (int)(255 * l->vg));
  590.     XtVaSetValues(l->greenText, XtNstring, buf, NULL);
  591.     XawScrollbarSetThumb(l->greenBar, l->vg, -1.0);
  592.     sprintf(buf, "%d", (int)(255 * l->vb));
  593.     XtVaSetValues(l->blueText, XtNstring, buf, NULL);
  594.     XawScrollbarSetThumb(l->blueBar, l->vb, -1.0);
  595. }
  596.  
  597. static void applyCB(Widget w, DialogInfo *l, XtPointer junk)
  598. {
  599.     XColor    xcol;
  600.     int    t;
  601.  
  602.     xcol.pixel = l->pixel;
  603.     xcol.flags = DoRed|DoGreen|DoBlue;
  604.     XQueryColor(XtDisplay(w), DefaultColormapOfScreen(XtScreen(w)), &xcol);
  605.  
  606.     backgroundRGB[0] = (xcol.red >> 8) & 0xff;
  607.     backgroundRGB[1] = (xcol.green >> 8) & 0xff;
  608.     backgroundRGB[2] = (xcol.blue >> 8) & 0xff;
  609.  
  610. #define STUFF(src, dst) \
  611.     t = (src) * 255; if (t < 0) t = 0; else if (t > 255) t = 255; dst = t
  612.  
  613.     STUFF(l->vr, varianceRGB[0]);
  614.     STUFF(l->vg, varianceRGB[1]);
  615.     STUFF(l->vb, varianceRGB[2]);
  616.  
  617. #undef STUFF
  618.  
  619.     if (l->mode != None)
  620.         cutMode = ((int)XawToggleGetCurrent(l->mode)) - 1;
  621.     OperationSelectCallAcross(cutMode);
  622. }
  623. static void okCB(Widget w, DialogInfo *l, XtPointer junk)
  624. {
  625.     applyCB(w,l,junk);
  626.     closePopup(w, GetShell(w));
  627. }
  628.  
  629. void SelectChromaDialog(Widget w)
  630. {
  631.     Widget            topform, form, cpick, ok, cancel, apply;
  632.     Widget            label, tog;
  633.     Widget            above;
  634.     DialogInfo        *l = dInfo;
  635.  
  636.     if (l != NULL && l->shell != None) {
  637.         if (l->mode != None)
  638.             XawToggleSetCurrent(l->mode, (XtPointer)(cutMode+1));
  639.         XtPopup(l->shell, XtGrabNone);
  640.         XMapRaised(XtDisplay(l->shell), XtWindow(l->shell));
  641.         return;
  642.     }
  643.  
  644.     dInfo = l = XtNew(DialogInfo);
  645.  
  646.     l->r = (float)backgroundRGB[0] / 255.0;
  647.     l->g = (float)backgroundRGB[1] / 255.0;
  648.     l->b = (float)backgroundRGB[2] / 255.0;
  649.     l->vr = (float)varianceRGB[0] / 255.0;
  650.     l->vg = (float)varianceRGB[1] / 255.0;
  651.     l->vb = (float)varianceRGB[2] / 255.0;
  652.  
  653.     l->shell = XtVaCreatePopupShell("chroma", topLevelShellWidgetClass, GetToplevel(w),
  654.                 NULL);
  655.  
  656.     topform = XtVaCreateManagedWidget("form", formWidgetClass, l->shell,
  657.                 NULL);
  658.  
  659.     /*
  660.     **  First create the list of toggle buttons for the mode selection
  661.     */
  662. #if 0
  663.     form = XtVaCreateManagedWidget("form", formWidgetClass, topform,
  664.                 XtNborderWidth, 0,
  665.                 NULL);
  666.  
  667.     label = XtVaCreateManagedWidget("selectModeLabel", labelWidgetClass, form,
  668.                 XtNborderWidth, 0,
  669.                 NULL);
  670.  
  671.     /*
  672.     **  radioData = mode + 1
  673.     */
  674.     tog = None;
  675.     tog = XtVaCreateManagedWidget("mode0", toggleWidgetClass, form,
  676.                 XtNfromVert, label,
  677.                 XtNradioGroup, tog,
  678.                 XtNradioData, 1,
  679.                 XtNstate, (cutMode == 0),
  680.                 NULL);
  681.     tog = XtVaCreateManagedWidget("mode1", toggleWidgetClass, form,
  682.                 XtNfromVert, tog,
  683.                 XtNradioGroup, tog,
  684.                 XtNradioData, 2,
  685.                 XtNstate, (cutMode == 1),
  686.                 NULL);
  687.     tog = XtVaCreateManagedWidget("mode2", toggleWidgetClass, form,
  688.                 XtNfromVert, tog,
  689.                 XtNradioGroup, tog,
  690.                 XtNradioData, 3,
  691.                 XtNstate, (cutMode == 2),
  692.                 NULL);
  693.     l->mode = tog;
  694. #else
  695.     l->mode = None;
  696. #endif
  697.  
  698.     /*
  699.     **  Now the color choser.
  700.     */
  701.     form = XtVaCreateManagedWidget("form", formWidgetClass, topform,
  702. #if 0
  703.                 XtNfromHoriz, form,
  704. #endif
  705.                 XtNborderWidth, 0,
  706.                 NULL);
  707.  
  708.     cpick = ColorPicker(form, DefaultColormapOfScreen(XtScreen(w)), NULL);
  709.     l->pixel = ColorPickerGetPixel(cpick);
  710.  
  711.     above = XtVaCreateManagedWidget("delta", commandWidgetClass, form,
  712.                 XtNfromVert, cpick,
  713.                 NULL);
  714.     XtAddCallback(above, XtNcallback, (XtCallbackProc)deltaCB, (XtPointer)l);
  715.     
  716.     above = addSB(form, above, "Red Variance",
  717.                 &l->redBar, &l->redText);
  718.     above = addSB(form, above, "Green Variance", 
  719.                 &l->greenBar, &l->greenText);
  720.     above = addSB(form, above, "Blue Variance", 
  721.                 &l->blueBar, &l->blueText);
  722.  
  723.         XtAddCallback(l->redBar, XtNjumpProc, (XtCallbackProc)barCB, (XtPointer)l);
  724.         XtAddCallback(l->greenBar, XtNjumpProc, (XtCallbackProc)barCB, (XtPointer)l);
  725.         XtAddCallback(l->blueBar, XtNjumpProc, (XtCallbackProc)barCB, (XtPointer)l);
  726.  
  727.         AddDestroyCallback(l->shell, (void (*)(Widget, void *, XEvent *))closePopup, l->shell);
  728.  
  729.     ok = XtVaCreateManagedWidget("ok", commandWidgetClass, form,
  730.                 XtNfromVert, above,
  731.                 NULL);
  732.     apply = XtVaCreateManagedWidget("apply", commandWidgetClass, form,
  733.                 XtNfromVert, above,
  734.                 XtNfromHoriz, ok,
  735.                 NULL);
  736.     cancel = XtVaCreateManagedWidget("cancel", commandWidgetClass, form,
  737.                 XtNfromVert, above,
  738.                 XtNfromHoriz, apply,
  739.                 NULL);
  740.     XtAddCallback(cancel, XtNcallback, (XtCallbackProc)closePopup, (XtPointer)l->shell);
  741.     XtAddCallback(apply, XtNcallback, (XtCallbackProc)applyCB, (XtPointer)l);
  742.     XtAddCallback(ok, XtNcallback, (XtCallbackProc)okCB, (XtPointer)l);
  743.  
  744.     XtPopup(l->shell, XtGrabNone);
  745. }
  746.  
  747. void SelectSetCutMode(int value)
  748. {
  749.     cutMode = value;
  750.  
  751.     if (dInfo != NULL && dInfo->mode != None)  
  752.         XawToggleSetCurrent(dInfo->mode, (XtPointer)(cutMode+1));
  753. }
  754.